﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Xml.Linq;
using Styx;
using Styx.Common;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.CommonBot.AreaManagement;
using Styx.CommonBot.Database;
using Styx.CommonBot.Frames;
using Styx.CommonBot.Inventory;
using Styx.CommonBot.Profiles;
using Styx.CommonBot.POI;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx.Plugins;
using Styx.WoWInternals;
using Styx.WoWInternals.Misc;
using Styx.WoWInternals.World;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;

using Sequence = Styx.TreeSharp.Sequence;
using Action = Styx.TreeSharp.Action;
using CommonBehaviors.Actions;
using Levelbot.Actions.Combat;

namespace Styx.Bot.CustomBots
{
    public class MultiboxLeader : BotBase
    {
        //***************************** do not edit above************************
        private bool IsTank = true; //Is the leader a tank, should it try to make sure everything is targeting him/her?
        //***************************** Do not edit below************************

        private List<WoWUnit> CombatList;
        //public readonly LocalPlayer Me = ObjectManager.Me;
        public static LocalPlayer Me { get { return StyxWoW.Me; } }
        private bool firstpulse = false;
        //private bool InCombat = false;

        private void slog(string format, params object[] args)
        {
            Logging.Write("[MBoxLeader] " + format, args);
        }

        private void Populate()
        {
            CombatList = ObjectManager.GetObjectsOfType<WoWUnit>()
            .Where(u => (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember) && !u.IsTargetingMeOrPet && u.CurrentTarget.Combat)
            .OrderBy(u => u.Distance).ToList();
        }

        private void CombatStart()
        {
            if (!IsTank)
            {
                foreach (WoWUnit Target in CombatList)
                {
                    if (Me.CurrentTarget != null)
                    {
                        if (!Me.CurrentTarget.Combat)
                        {
                            CombatList[0].Target();
                        }
                    }
                    else
                    {
                        CombatList[0].Target();
                    }

                }
            }
            else if (IsTank)
            {
                if (CombatList.Count >= 1)
                {
                    CombatList[0].Target();
                }
            }
        }




        #region Overrides of BotBase

        public override string Name
        {
            get { return string.Format("Multibox Leader"); }
        }

        private Composite _root;
        public override Composite Root
        {
            get
            {
                return _root ?? (_root =
                    new PrioritySelector(
                        CreateCombatBehavior()
                        )
                    );
            }
        }

        public override void Pulse()
        {
            Populate();
            CombatStart();

            if (!firstpulse)
            {
                slog("Multibox Leader version 3.9.8");
                if (!IsTank)
                {
                    slog("Tanking is disabled");
                }
                else
                {
                    slog("Tanking is enabled");
                }
                firstpulse = true;
            }
            //if (Me.Combat || CombatList.Count >= 1)
            //{
            //    InCombat = true;
            //}
            //else
            //{
            //    InCombat = false;
            //}
        }

        public override PulseFlags PulseFlags
        {
            get { return PulseFlags.All; }
        }

        public override void Start()
        {
            Targeting.Instance.IncludeTargetsFilter += IncludeTargetsFilter;
            GlobalSettings.Instance.LogoutForInactivity = false;
        }

        public override void Stop()
        {
            Targeting.Instance.IncludeTargetsFilter -= IncludeTargetsFilter;
            GlobalSettings.Instance.LogoutForInactivity = true;
        }

        #endregion

        #region Targeting Filter

        private static void IncludeTargetsFilter(List<WoWObject> incomingUnits, HashSet<WoWObject> outgoingUnits)
        {
            if (StyxWoW.Me.GotTarget && StyxWoW.Me.CurrentTarget.Attackable)
            {
                outgoingUnits.Add(StyxWoW.Me.CurrentTarget);
            }
        }

        #endregion

        #region Behaviors

        #region Combat Behavior

        private static bool NeedPull(object context)
        {
            var target = StyxWoW.Me.CurrentTarget;

            if (target == null)
                return false;

            if (!target.InLineOfSight)
                return false;

            if (target.Distance > Targeting.PullDistance)
                return false;

            return true;
        }

        private static Composite CreateCombatBehavior()
        {
            return new PrioritySelector(

                new Decorator(ret => !StyxWoW.Me.Combat,
                    new PrioritySelector(

            #region PreCombatBuffs

new PrioritySelector(
                // new ActionDebugString("[Combat] Checking PCBBehavior"),
                // Use the bt
                            new Decorator(ctx => RoutineManager.Current.PreCombatBuffBehavior != null,
                                RoutineManager.Current.PreCombatBuffBehavior),

                            // don't use the bt
                // new ActionDebugString("[Combat] Checking PCBOld"),
                            new Decorator(
                                ctx => RoutineManager.Current.NeedPreCombatBuffs,
                                new Sequence(
                                    new Action(ret => TreeRoot.StatusText = "Applying pre-combat buffs"),
                                    new Action(ret => RoutineManager.Current.PreCombatBuff())
                                    ))),

            #endregion

            #region Pull

                // new ActionDebugString("[Combat] Pull"),
                // Don't pull, unless we've decided to pull already.
                        new Decorator(ret => BotPoi.Current.Type == PoiType.Kill,
                            new PrioritySelector(

                                // Make sure we have a valid target list.
                                new Decorator(ret => Targeting.Instance.TargetList.Count != 0,
                // Force the 'correct' POI to be our target.
                                    new Decorator(ret => BotPoi.Current.AsObject != Targeting.Instance.FirstUnit &&
                                        BotPoi.Current.Type == PoiType.Kill,
                                        new Sequence(

                                            new Action(ret => BotPoi.Current = new BotPoi(Targeting.Instance.FirstUnit, PoiType.Kill)),
                                            new Action(ret => BotPoi.Current.AsObject.ToUnit().Target())))),

                                        new Decorator(NeedPull,
                                            new PrioritySelector(
                                                new Decorator(ctx => RoutineManager.Current.PullBuffBehavior != null,
                                                    RoutineManager.Current.PullBuffBehavior),

                                                new Decorator(ctx => RoutineManager.Current.PullBehavior != null,
                                                    RoutineManager.Current.PullBehavior),

                                                    new ActionPull())))))),
            #endregion

 new Decorator(ret => StyxWoW.Me.Combat,

                    new PrioritySelector(

            #region Heal

new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.HealBehavior != null,
                                new Sequence(
                                    RoutineManager.Current.HealBehavior,
                                    new Action(delegate { return RunStatus.Success; })
                                    )),

                            // Don't use the Behavior
                            new Decorator(ctx => RoutineManager.Current.NeedHeal,
                                new Sequence(
                                    new Action(ret => TreeRoot.StatusText = "Healing"),
                                    new Action(ret => RoutineManager.Current.Heal())
                                    ))),

            #endregion

            #region Combat Buffs

 new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.CombatBuffBehavior != null,
                                        new Sequence(
                                            RoutineManager.Current.CombatBuffBehavior,
                                            new Action(delegate { return RunStatus.Success; })
                                            )
                                ),

                            // Don't use the Behavior
                            new Decorator(ctx => RoutineManager.Current.NeedCombatBuffs,
                                        new Sequence(
                                            new Action(ret => TreeRoot.StatusText = "Applying Combat Buffs"),
                                            new Action(ret => RoutineManager.Current.CombatBuff())
                                            ))),

            #endregion

            #region Combat

 new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.CombatBehavior != null,
                                new PrioritySelector(
                                    RoutineManager.Current.CombatBehavior,
                                    new Action(delegate { return RunStatus.Success; })
                                    )),

                            // Don't use the Behavior
                            new Sequence(
                                new Action(ret => TreeRoot.StatusText = "Combat"),
                                new Action(ret => RoutineManager.Current.Combat())))

            #endregion

)),

            new Decorator(ret => StyxWoW.Me.CurrentTarget != null && !StyxWoW.Me.IsDead && !StyxWoW.Me.IsGhost,
                new Decorator(ret => (StyxWoW.Me.CurrentTarget.IsTargetingMyPartyMember || StyxWoW.Me.CurrentTarget.IsTargetingMyRaidMember) && !StyxWoW.Me.CurrentTarget.IsDead && (StyxWoW.Me.CurrentTarget.IsNeutral || StyxWoW.Me.CurrentTarget.IsHostile),

                    new PrioritySelector(

            #region Heal

new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.HealBehavior != null,
                                new Sequence(
                                    RoutineManager.Current.HealBehavior,
                                    new Action(delegate { return RunStatus.Success; })
                                    )),

                            // Don't use the Behavior
                            new Decorator(ctx => RoutineManager.Current.NeedHeal,
                                new Sequence(
                                    new Action(ret => TreeRoot.StatusText = "Healing"),
                                    new Action(ret => RoutineManager.Current.Heal())
                                    ))),

            #endregion

            #region Combat Buffs

 new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.CombatBuffBehavior != null,
                                        new Sequence(
                                            RoutineManager.Current.CombatBuffBehavior,
                                            new Action(delegate { return RunStatus.Success; })
                                            )
                                ),

                            // Don't use the Behavior
                            new Decorator(ctx => RoutineManager.Current.NeedCombatBuffs,
                                        new Sequence(
                                            new Action(ret => TreeRoot.StatusText = "Applying Combat Buffs"),
                                            new Action(ret => RoutineManager.Current.CombatBuff())
                                            ))),

            #endregion

            #region Combat

 new PrioritySelector(
                // Use the Behavior
                            new Decorator(ctx => RoutineManager.Current.CombatBehavior != null,
                                new PrioritySelector(
                                    RoutineManager.Current.CombatBehavior,
                                    new Action(delegate { return RunStatus.Success; })
                                    )),

                            // Don't use the Behavior
                            new Sequence(
                                new Action(ret => TreeRoot.StatusText = "Combat"),
                                new Action(ret => RoutineManager.Current.Combat())))

            #endregion

))));
        }

        #endregion


        #endregion
    }
}

